using System.Runtime.Serialization;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using FarseerPhysics.Dynamics;
using INdT.Sparta.Physics; 

namespace INdT.Sparta.Graphics
{
    [DataContract]
    public class SpartaTexture : SpartaDrawable
    {
        public virtual Texture2D Texture { get; set; }

        public override int Width
        {
            get { return SourceRect.Width > 0 ? SourceRect.Width : (Texture == null ? 0 : Texture.Width); }
        }

        public override int Height
        {
            get { return SourceRect.Height > 0 ? SourceRect.Height : (Texture == null ? 0 : Texture.Height); }
        }

        public override float X
        {
            get
            {
                if (PhysicsObject == null)
                {
                    return base.X;
                }
                else
                {
                    float value = PhysicsObject.Position.X * SpartaPhysics.MeterPerPixel;
                    base.X = value;
                    return value;
                }
            }
            set
            {
                if (PhysicsObject != null)
                {
                    Vector2 position = PhysicsObject.Position;
                    position.X = value / SpartaPhysics.MeterPerPixel;
                    PhysicsObject.Position = position;
                }
                base.X = value;
            }
        }

        public override float Y
        {
            get
            {
                if (PhysicsObject == null)
                {
                    return base.Y;
                }
                else
                {
                    float value = PhysicsObject.Position.Y * SpartaPhysics.MeterPerPixel;
                    base.Y = value;
                    return value;
                }
            }
            set
            {
                if (PhysicsObject != null)
                {
                    Vector2 position = PhysicsObject.Position;
                    position.Y = value / SpartaPhysics.MeterPerPixel;
                    PhysicsObject.Position = position;
                }
                base.Y = value;
            }
        }

        public override Vector2 Position
        {
            get
            {
                if (PhysicsObject == null)
                {
                    return base.Position;
                }
                else
                {
                    Vector2 value = PhysicsObject.Position * SpartaPhysics.MeterPerPixel;
                    base.Position = value;
                    return value;
                }
            }
            set
            {
                if (PhysicsObject != null)
                {
                    PhysicsObject.Position = value / SpartaPhysics.MeterPerPixel;
                }
                base.Position = value;
            }
        }

        public override float Angle
        {
            get
            {
                if (PhysicsObject == null)
                {
                    return base.Angle;
                }
                else
                {
                    float value = PhysicsObject.Rotation;
                    base.Angle = value;
                    return value;
                }
            }
            set
            {
                if (PhysicsObject != null)
                {
                    PhysicsObject.Rotation = value;
                }
                base.Angle = value;
            }
        }

        [DataMember]
        public virtual string TextureAssetName { get; set; }

        [DataMember]
        public virtual Rectangle SourceRect { get; set; }

        public Body PhysicsObject;

        public SpartaTexture()
            : this(string.Empty)
        {
        }

        public SpartaTexture(string imageName)
        {
            TextureAssetName = imageName;
            PhysicsObject = null;
        }

        public override void LoadContent()
        {
            if (string.IsNullOrEmpty(TextureAssetName))
            {
                return;                
            }

            Texture = SpartaGame.Instance.LoadTexture(TextureAssetName);            
        }

        public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            if (Texture == null || !Visible)
            {
                base.Draw(gameTime, spriteBatch);
                return;
            }

            if (SourceRect.IsEmpty)
            {
                spriteBatch.Draw(Texture, Position, null, Color, Angle, Origin, Scale, SpriteEffect, LayerDepth);
            }
            else
            {
                spriteBatch.Draw(Texture, Position, SourceRect, Color, Angle, Origin, Scale, SpriteEffect, LayerDepth);
            }

            base.Draw(gameTime, spriteBatch);
        }

        public override void Dispose()
        {
            Texture = null;
            if (PhysicsObject != null)
            {
                PhysicsObject.Dispose();
                PhysicsObject = null;
            }
            base.Dispose();
        }
    }
}
